package point

import (
	"time"

	"mongo-stress/jsonprotocol"
)

// Point 表示 MongoDB 的时间序列数据点
type Point struct {
	Tags      map[string]string      `bson:"tags"`      // 多个 tag
	FieldsMap map[string]interface{} `bson:"fields"`    // 多个 field
	Timestamp time.Time              `bson:"timestamp"` // 时间戳
}

// ------------------- 实现 lineprotocol.Point 接口 -------------------

// Series 返回序列 key，可以简单拼接 tags
func (p *Point) Series() []byte {
	// 拼接 tags 作为 series key: sensor_id=1,region=us-east,...
	key := ""
	for k, v := range p.Tags {
		if key != "" {
			key += ","
		}
		key += k + "=" + v
	}
	return []byte(key)
}

// Fields 返回 Field 切片（lineprotocol.Field 是 io.WriterTo 的别名）
func (p *Point) Fields() []jsonprotocol.Field {
	fields := make([]jsonprotocol.Field, 0, len(p.FieldsMap))
	for k, v := range p.FieldsMap {
		fields = append(fields, jsonprotocol.NewField(k, v))
	}
	return fields
}

// Time 返回时间戳
func (p *Point) Time() *jsonprotocol.Timestamp {
	// 转换成纳秒时间戳
	return jsonprotocol.NewTimestamp(p.Timestamp, jsonprotocol.Nanosecond)
}

// SetTime 设置时间戳
func (p *Point) SetTime(t time.Time) {
	p.Timestamp = t
}

// CloneFields 克隆字段
func (p *Point) CloneFields() map[string]interface{} {
	newMap := make(map[string]interface{}, len(p.FieldsMap))
	for k, v := range p.FieldsMap {
		newMap[k] = v
	}
	return newMap
}

func (p *Point) Update(fields map[string]interface{}) {
	// 示例：模拟传感器数值变化
	for k, v := range fields {
		switch val := v.(type) {
		case int:
			p.FieldsMap[k] = val
		case float64:
			p.FieldsMap[k] = val
		case bool:
			p.FieldsMap[k] = !val
		}
	}
}

// ---------------- Point 数据生成 ----------------

func New(tags map[string]string, fields map[string]interface{}) *Point {
	fieldsInterface := make(map[string]interface{}, len(fields))
	for k, v := range fields {
		fieldsInterface[k] = v
	}

	return &Point{
		Tags:      tags,
		FieldsMap: fieldsInterface,
		Timestamp: time.Now(),
	}
}

// GeneratePoints 根据 tags template 和 fields template 生成 Point 列表
func NewPoints(tagsTemplate, fieldsTemplate string, seriesN int) []*Point {
	series := generateSeriesKeys(tagsTemplate, seriesN)
	fieldsDef := ParseFieldsTemplate(fieldsTemplate)

	points := make([]*Point, len(series))
	for i, tags := range series {
		fields := make(map[string]interface{})
		for name, typ := range fieldsDef {
			fields[name] = GenerateFieldValue(typ)
		}
		points[i] = New(tags, fields)
	}
	return points
}
